package com.dream.libxrec.rec;

import android.media.MediaCodec;
import android.media.MediaFormat;
import android.media.MediaMuxer;
import android.util.Log;

import java.io.IOException;
import java.nio.ByteBuffer;

public class Mp4MediaMuxer {
    private MediaMuxer mMediaMuxer;
    private int mVideoTrackIndex = -1;
    private int mAudioTrackIndex = -1;
    private final static String TAG = "Mp4MediaMuxer";
    private long mStartMs = -1;
    private IMuxerBuilder mMuxerBuilder = null;
    private MediaFormat mAudioFormat,mVideoFormat;
    private String mRecordPath = null;

    public synchronized void start(MediaFormat audio,
                                   MediaFormat video, IMuxerBuilder builder){

        this.mMuxerBuilder = builder;
        mRecordPath = builder.getFilePath();
        try {
            mMediaMuxer = new MediaMuxer(mRecordPath,
                    MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);

            if (audio != null){
                mAudioFormat = audio;
                mAudioTrackIndex = mMediaMuxer.addTrack(audio);
            }

            if (video != null){
                mVideoFormat = video;
                mVideoTrackIndex = mMediaMuxer.addTrack(video);
            }
            mStartMs = -1;
            mMediaMuxer.start();
        } catch (IOException e) {
            e.printStackTrace();
        }

        Log.i(TAG,"开始录制:"+mRecordPath);
    }

    public synchronized void stop(){
        if (mMediaMuxer != null) {
            mVideoTrackIndex = -1;
            mAudioTrackIndex = -1;
            mMediaMuxer.release();
            mMediaMuxer = null;
            Log.i(TAG,"录制结束:"+mRecordPath);
        }
    }

    public synchronized void writeAudioFrame(ByteBuffer buffer,
                                             MediaCodec.BufferInfo info){
        if (mAudioTrackIndex == -1){
            return;
        }
        writeData(buffer,info,mAudioTrackIndex);
    }

    public synchronized void writeVideoFrame(ByteBuffer buffer,
                                             MediaCodec.BufferInfo info){
        if (mVideoTrackIndex == -1){
            return;
        }
        writeData(buffer,info,mVideoTrackIndex);
    }

    private void writeData(ByteBuffer outputBuffer,
                    MediaCodec.BufferInfo bufferInfo, int track) {

        if (bufferInfo.flags == MediaCodec.BUFFER_FLAG_KEY_FRAME){
            if (mStartMs > 0&&mMuxerBuilder.isEndFile(bufferInfo.presentationTimeUs - mStartMs)){
                stop();
                start(mAudioFormat,mVideoFormat,mMuxerBuilder);
            }
        }

        if (mStartMs == -1){
            mStartMs = bufferInfo.presentationTimeUs;
        }

        if ((bufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {
            bufferInfo.size = 0;
        } else if (bufferInfo.size != 0) {
            if (mMediaMuxer == null){
                return;
            }
            outputBuffer.position(bufferInfo.offset);
            outputBuffer.limit(bufferInfo.offset + bufferInfo.size);
            mMediaMuxer.writeSampleData(track, outputBuffer, bufferInfo);
        }
    }

    public interface IMuxerBuilder {
        /**
         * 获取文件路径
         * @return
         */
        public String getFilePath();

        /**
         * 是否结束文件,重新创建一个文件
         * @param recTime 当前文件已录制时长，单位为微秒
         * @return
         */
        public boolean isEndFile(long recTime);
    }
}
